import { _decorator, Node, Button, Label, Prefab, Vec3 } from 'cc';
import { BasePanel } from '../../../../scripts/libs/ui/BasePanel';
import { IntervalStartNow, Timer } from '../../../../scripts/libs/rxjs/cc3/CreatorSchedule';
import { udm } from '../../../../scripts/managers/UserDataManager';
import { MSResolve } from '../../../../scripts/libs/utils/date';
import { DevConfig, ItemKey } from '../../../../scripts/managers/DevConfig';
import { instantiate } from 'cc';
import { LuckyWheelItem } from './LuckyWheelItem';
import { BindButton } from '../../../../scripts/libs/rxjs/cc3/BindButton';
import { gm } from '../../../../scripts/managers/GameManager';
import { concat, forkJoin, Subscription, tap } from 'rxjs';
import { nullifySubscription } from '../../../../scripts/libs/rxjs/utils';
import { instantFunc } from '../../../../scripts/libs/rxjs/cc3/CommonObservable';
import { ReactiveProperty } from '../../../../scripts/libs/rxjs/cc3/ReactiveProperty';
import { lm } from '../../LobbyManager';
import { SpriteFrame } from 'cc';
import { JumpTo_2D, TweenToStart } from '../../../../scripts/libs/rxjs/cc3/TweenStart';
import { v3 } from 'cc';
import { Animation } from 'cc';
import { ProvideInfo } from '../../../../scripts/managers/SDK/IapSDKManager';
import { director } from 'cc';
import { ResourceHelper } from '../../ResourceHelper';
import { UIOpacity } from 'cc';
import { FlyItem } from '../../game/FlyItem';
import { UITransform } from 'cc';
import { nc } from '../../../../scripts/libs/rxjs/NotificationCenter';
import { thinking_sdk_m } from '../../../../scripts/managers/SDK/ThinkingCocosSDKManager';
import { Sprite } from 'cc';
import { color } from 'cc';
import { ResizeToFullScreen } from '../../../../scripts/libs/utils/Component/ResizeToFullScreen';
import { taskm } from '../../../../scripts/managers/TaskManager';
const { ccclass, property } = _decorator;

@ccclass('LuckyWheelPanel')
export class LuckyWheelPanel extends BasePanel {

    @property(Node)
    mainNode: Node = null;

    @property(Button)
    closeButton: Button = null;

    @property(Label)
    remainLabel: Label = null;

    @property(Node)
    wheelContainer: Node = null;

    @property(Button)
    spinButton: Button = null;

    @property(Node)
    arrowNode: Node = null;

    choosedIdx = ReactiveProperty.Create<number>(null);

    @property([SpriteFrame])
    itemSpriteFrames: SpriteFrame[] = [];

    @property([SpriteFrame])
    coinSpriteFrames: SpriteFrame[] = [];

    @property(Prefab)
    luckyWheelItemPrefab: Prefab = null;

    @property(Node)
    flyFromNode: Node = null;

    @property(Node)
    coverNode: Node = null;

    @property(Node)
    coverBgNode: Node = null;

    willBind(): void {
        lm.luckyWheelPanelOpened.value = true;
        this.coverNode.active = false;
        this.adaptive();
    }

    useObserves() {
        return [
            IntervalStartNow(1, this.node).subscribe(this.refresh.bind(this)),
            BindButton(this.closeButton).subscribe(this.closeButtonClicked.bind(this)),
            BindButton(this.spinButton).subscribe(this.spinButtonClicked.bind(this)),
            udm.luckyWheelSpinCount.subscribe(this.refresh.bind(this)),
        ];
    }

    adaptive() {
        this.mainNode.setScale(v3(Vec3.ONE).multiplyScalar(lm.getAdaptiveScale()));
        this.getComponentsInChildren(ResizeToFullScreen).forEach(_ => _.adapt());
    }

    onLoadView(): void {
        this.genItems();
    }

    onDestroyView(): void {
        nullifySubscription.call(this, '_sub_spin_anim');
        lm.luckyWheelPanelOpened.value = false;
    }

    refresh() {
        let ms = udm.getRemainMsToNextDay();

        if (ms < 0) {
            udm.luckyWheelRefreshStorage();
            return;
        }

        let msr = MSResolve(ms);
        // this.remainLabel.string = `Reset: ${MSRToString_th_m_s(msr)}`;
        this.remainLabel.string = `Spins left: ${DevConfig.LUCKYWHEEL.DAILY_TIMES - udm.luckyWheelSpinCount.value}`;

        // this.spinButtonLabel.string = `Spin(${udm.luckyWheelSpinCount.value}/${DevConfig.LUCKYWHEEL.DAILY_TIMES})`;
        if (udm.luckyWheelSpinCount.value < DevConfig.LUCKYWHEEL.DAILY_TIMES) {
            this.spinButton.interactable = true;
            // taskm.checkInc('spin_wheel');
            this.spinButton.getComponentsInChildren(Sprite).forEach(_ => _.grayscale = false);
            this.spinButton.getComponentsInChildren(Label).forEach(_ => _.outlineColor = color().fromHEX('00538D'));
        } else {
            this.spinButton.interactable = false;
            this.spinButton.getComponentsInChildren(Sprite).forEach(_ => _.grayscale = true);
            this.spinButton.getComponentsInChildren(Label).forEach(_ => _.outlineColor = color().fromHEX('777777'));
        }
    }

    genItems() {
        for (let i = 0; i < DevConfig.LUCKYWHEEL.rewards.probability.length; i++) {
            let data = DevConfig.LUCKYWHEEL.rewards.probability[i];
            let node = instantiate(this.luckyWheelItemPrefab);
            let item = node.getComponent(LuckyWheelItem);
            item.panel = this;
            item.data.value = data;
            node.setParent(this.wheelContainer);
            let angle = 45 * i - 67;
            item.node.setRotationFromEuler(0, 0, angle);
        }
    }

    _sub_spin_anim: Subscription = null;
    spinButtonClicked() {
        if (udm.luckyWheelSpinCount.value < DevConfig.LUCKYWHEEL.DAILY_TIMES) {
            gm.coinAnimatingFlags.add('lucky_wheel');
            gm.heartAnimatingFlags.add('lucky_wheel');
            gm.itemAnimatingFlags.add('lucky_wheel');
            let choosed = udm.luckyWheelSpin();
            this.thinking(choosed.provide, 'LuckySpin');
            nullifySubscription.call(this, '_sub_spin_anim');

            taskm.checkInc('spin_wheel');

            this._sub_spin_anim = this.spinAnimate(choosed.idx).subscribe({
                complete: () => {

                    this.choosedAnimate(choosed).subscribe({
                        complete: () => {
                            this.flyProvide(choosed.provide);
                            gm.coinAnimatingFlags.delete('lucky_wheel');
                            gm.heartAnimatingFlags.delete('lucky_wheel');
                            gm.itemAnimatingFlags.delete('lucky_wheel');
                        }
                    });


                }
            });
        }
        // lm.frontTipShow('')
    }

    closeButtonClicked() {
        LuckyWheelPanel.CloseProcess(null, 'close');

        // test 退出就重置
        // udm.luckyWheelReset();
    }

    spinAnimate(idx: number) {
        this.choosedIdx.value = null;
        let last_angle = -45 * idx + 67 + 360 * 20;
        this.log('@spinAnimate', idx, last_angle);

        let lastAngle = null;

        return concat(
            TweenToStart(this.wheelContainer, .25, { eulerAngles: v3(0, 0, this.wheelContainer.eulerAngles.z - 15) }, { easing: 'circOut' }),
            TweenToStart(this.wheelContainer, 4.5, { eulerAngles: v3(0, 0, last_angle) }, { easing: 'quintOut' }).pipe(tap(_ => {
                // this.log('tap:', _);
                if (_.status == 'update') {
                    let curAngle = this.wheelContainer.eulerAngles.z;
                    if (lastAngle != null) {
                        let lastGridId = Math.floor(lastAngle / 45);
                        let curGridId = Math.floor(curAngle / 45);
                        // this.log('>>', lastGridId, curGridId);

                        if (lastGridId != curGridId) {
                            this.arrowNode.getComponent(Animation).play();
                        }
                    }
                    lastAngle = curAngle;
                }
            })),
            instantFunc(() => {
                this.choosedIdx.value = idx;
                last_angle %= 360;
                this.wheelContainer.setRotationFromEuler(0, 0, last_angle); // 还原单倍角度，为了下一次旋转
            })
        );
    }

    // _sub_choosed_anim: Subscription = null;
    choosedAnimate(param: { idx: number, provide: ProvideInfo, p: number }) {
        // nullifySubscription.call(this._sub_choosed_anim);

        this.coverNode.active = true;
        this.coverBgNode.getComponent(UIOpacity).opacity = 0;

        let node = instantiate(this.luckyWheelItemPrefab);
        let item = node.getComponent(LuckyWheelItem);
        item.panel = this;
        item.data.value = param;
        node.setParent(this.coverNode);
        node.setWorldPosition(this.wheelContainer.worldPosition);
        item.node.setRotationFromEuler(0, 0, 0);
        item.rootNode.getComponent(UIOpacity).opacity = 0;

        return concat(
            forkJoin([
                TweenToStart(item.rootNode.getComponent(UIOpacity), .4, { opacity: 255 }, { easing: 'quadInOut' }),
                TweenToStart(this.coverBgNode.getComponent(UIOpacity), .4, { opacity: 255 }, { easing: 'quadOut' }),
            ]),
            forkJoin([
                JumpTo_2D(item.node, .5, v3(0, -250, 0), 200, { easing: 'quadInOut' }),
                // TweenToStart(item.node, .4, { position: v3(0, -250, 0) }, { easing: 'quadInOut' }),
                TweenToStart(item.rootNode, .4, { scale: v3(1.5, 1.5, 1.5) }, { easing: 'quadInOut' }),
            ]),
            Timer(1, this.node),
            instantFunc(() => {
                node.destroy();
                concat(
                    TweenToStart(this.coverBgNode.getComponent(UIOpacity), .4, { opacity: 0 }, { easing: 'quadInOut' }),
                    instantFunc(() => {
                        this.coverNode.active = false;
                    }),
                ).subscribe().addTo(this.node);

            })
        )
    }


    flyProvide(provide: ProvideInfo) {
        if (provide != null) {
            let lobbyPanel = director.getScene().getComponentInChildren('LobbyPanel') as any;
            if (lobbyPanel?.node.isValid) {
                let homeNode = lobbyPanel.lobbyHomeButton.node;
                let homeWorldPos = v3(homeNode.worldPosition);
                // Item
                ['swapper', 'magnet', 'balloon'].forEach(itemKey => {
                    if (provide[itemKey] > 0) {
                        let flyItemNode = ResourceHelper.FlyItemPool.getNode();
                        flyItemNode.setScale(1.5, 1.5, 1.5);
                        flyItemNode.getComponent(UIOpacity).opacity = 255;
                        flyItemNode.setParent(lm.uiRoot.tierFrontNode);
                        flyItemNode.setWorldPosition(this.flyFromNode.worldPosition);
                        flyItemNode.getComponent(FlyItem).itemKey.value = itemKey as ItemKey;
                        let targetLocalPos = v3();
                        lm.uiRoot.tierFrontNode.getComponent(UITransform).convertToNodeSpaceAR(homeWorldPos, targetLocalPos);
                        concat(
                            forkJoin([
                                // TweenToStart(flyItemNode, .6, { worldPosition: homeWorldPos }, { easing: 'quadInOut' }),
                                JumpTo_2D(flyItemNode, .8, targetLocalPos, 200, { easing: 'quadInOut' }),
                                concat(
                                    TweenToStart(flyItemNode, .3, { scale: v3(1.3, 1.3, 1.3) }, { easing: 'quadOut' }),
                                    TweenToStart(flyItemNode, .3, { scale: v3(1, 1, 1) }, { easing: 'quadIn' }),
                                ),
                                concat(
                                    Timer(.7),
                                    TweenToStart(flyItemNode.getComponent(UIOpacity), .1, { opacity: 0 }),
                                ),
                            ]),
                            instantFunc(() => {
                                flyItemNode.setScale(1, 1, 1);
                                ResourceHelper.FlyItemPool.putNode(flyItemNode);
                            })
                        ).subscribe()
                    }
                });
                ['coin'].forEach(itemKey => {
                    if (provide[itemKey] > 0) {
                        nc.post('fly_coins', { fromWorldPos: this.flyFromNode.worldPosition, count: provide[itemKey] });
                    }
                });
            }
        }
    }

    thinking(provide: ProvideInfo, type: string) {
        if (provide.coin > 0) {
            thinking_sdk_m.requestTrack('Coins_Get', {
                CoinNum: provide.coin,
                Type: type,
                Gift_Detail: 'Other',
                IsNew: udm.isNew.value,
                Level_ID: udm.stageNum.value,
                Booster_Itemdetail: `Swapper:${udm.itemSwapper.value}|Magnet:${udm.itemMagnet.value}|Balloon:${udm.itemBalloon.value}`
            });
        } else if (provide.swapper > 0) {
            thinking_sdk_m.requestTrack('Item_Get', {
                ItemType: 'swapper',
                CType: type,
                UseType: 'Num',
                ItemNum: provide.swapper,
                ItemAll: udm.itemSwapper.value,
                Level_ID: udm.stageNum.value,
                IsNew: udm.isNew.value,
                Booster_Itemdetail: `Swapper:${udm.itemSwapper.value}|Magnet:${udm.itemMagnet.value}|Balloon:${udm.itemBalloon.value}`
            });
        } else if (provide.magnet > 0) {
            thinking_sdk_m.requestTrack('Item_Get', {
                ItemType: 'magnet',
                CType: type,
                UseType: 'Num',
                ItemNum: provide.magnet,
                ItemAll: udm.itemMagnet.value,
                Level_ID: udm.stageNum.value,
                IsNew: udm.isNew.value,
                Booster_Itemdetail: `Swapper:${udm.itemSwapper.value}|Magnet:${udm.itemMagnet.value}|Balloon:${udm.itemBalloon.value}`
            });
        } else if (provide.balloon > 0) {
            thinking_sdk_m.requestTrack('Item_Get', {
                ItemType: 'balloon',
                CType: type,
                UseType: 'Num',
                ItemNum: provide.balloon,
                ItemAll: udm.itemBalloon.value,
                Level_ID: udm.stageNum.value,
                IsNew: udm.isNew.value,
                Booster_Itemdetail: `Swapper:${udm.itemSwapper.value}|Magnet:${udm.itemMagnet.value}|Balloon:${udm.itemBalloon.value}`
            });
        }
        // TODO: 如果宝箱里面有体力的奖励，也应该在此补充
    }
    // spinAnimate(idx: number) {
    //     let totalCount = DevConfig.LUCKYWHEEL.rewards.probability.length;
    //     let jump_times = Math.floor(Math.random() * 5 + 10);
    //     let total_duration = jump_times * .1;
    //     let start_idx = (idx - jump_times + totalCount * 100) % totalCount;
    //     return new Observable(observer => {
    //         let sub = IntervalWithTween(total_duration, jump_times, easing.quadOut).subscribe({
    //             next: _ => {
    //                 let cur_idx = (start_idx + _ + 1) % totalCount;
    //                 this.log('idx', cur_idx);
    //                 this.choosedIdx.value = cur_idx;
    //             },
    //             complete: () => {
    //                 observer.nextAndComplete(null);
    //             }
    //         })
    //         return () => {
    //             sub.unsubscribe();
    //             sub = null;
    //         }
    //     });
    // }
}

